// 处理HC-SR04超声波传感器的回声信号，并计算距离
//   Description  ﹕超声波检测距离模块
// 本模块理论测试距离 2cm~510cm
// 输出结果保留两位小数
module hc_sr_echo
(
    input logic Clk,        // 输入50MHz时钟信号
    input logic clk_us,     // 输入1MHz系统时钟信号
    input logic Rst_n,      // 输入复位信号，低电平有效
    
    input logic echo,       // 输入超声波回声信号
    output logic [18:0] data_o  // 输出检测到的距离，以厘米为单位，保留三位小数
);

/* 		S(um) = 17 * t 		-->  x.abc cm	*/
//Parameter Declarations
    parameter T_MAX = 16'd60_000; // 定义计数器的最大值，对应510厘米

    logic r1_echo, r2_echo;  // 用于边沿检测的寄存器
    logic echo_pos, echo_neg;  // 回声信号的上升沿和下降

    logic [15:0] cnt;  // 1MHz时钟下的计数器，用于测量回声脉冲宽度
    logic add_cnt;  // 计数器使能信号
    logic end_cnt;  // 计数器结束信号
    
    logic [18:0] data_r;  // 距离数据的中间寄存器

    // 逻辑描述
    // 使用50MHz时钟检测回声信号的边沿，以避免使用1MHz时钟导致的2us延时
    always_ff @(posedge Clk or negedge Rst_n) begin
        if (!Rst_n) begin
            r1_echo <= 1'b0;
            r2_echo <= 1'b0;
        end
        else begin
            r1_echo <= echo;
            r2_echo <= r1_echo;
        end
    end

    // 产生上升沿和下降沿信号
    assign echo_pos = r1_echo & ~r2_echo;  // 回声信号上升沿
    assign echo_neg = ~r1_echo & r2_echo;  // 回声信号下降沿
    
    // 计数器逻辑，用于测量回声脉冲宽度
    always_ff @(posedge clk_us or negedge Rst_n) begin
        if (!Rst_n) begin
            cnt <= '0; 
        end
        else if (add_cnt) begin
            if (end_cnt) begin
                cnt <= cnt;  // 如果达到最大测量范围，则保持当前计数值
            end
            else begin
                cnt <= cnt + 1'b1; // 否则计数器递增
            end
        end
        else begin  // 如果回声信号低电平，计数器归零
            cnt <= '0;
        end
    end
    
    assign add_cnt = echo; // 赋值计数器使能信号，当回声信号为高电平时使能计数器
    assign end_cnt = add_cnt && cnt >= T_MAX - 1; //赋值计数器结束信号，当计数器达到最大值T_MAX时有效 超出最大测量范围则保持不变，极限

    // 测试距离=(高电平时间*声速(340M/S))/2;
    // 距离数据处理逻辑，将计数值转换为距离
    always_ff @(posedge Clk or negedge Rst_n) begin
        if (!Rst_n) begin
            data_r <= 'd2;  // 复位时中间寄存器置为2，用于小数点后三位的计算
        end
        else if (echo_neg) begin
            // 当回声信号下降沿到来时，将计数值左移四位并加上自身，实现小数点后三位的计算
            //t = cnt*1000ns = cnt*10-6s
            //s = 340*t m
            data_r <= (cnt << 4) + cnt;
        end
        else begin
            data_r <= data_r;  // 否则保持当前值
        end
    end

    // 将中间寄存器的数据右移一位，实现除以2的操作，得到最终的距离数据
    assign data_o = data_r >> 1;

endmodule